<?php

namespace App\Models;

use App\Utils\TradeNoGeneratorUtil;
use Illuminate\Database\Eloquent\Model;
use Ramsey\Uuid\Uuid;

class Order extends Model
{
    public const ORDER_CLOSED = 1;  // 订单已经关闭

    public const PAYMENT_METHOD_LJSH = 'ljsh';  // 余额抵扣、优惠券使用后，订单金额为 0 的情况，不调用第三方支付接口
    public const PAYMENT_METHOD_WECHAT = 'wechat'; // 支付方式，微信
    public const PAYMENT_METHOD_ALIPAY = 'alipay'; // 支付宝
    public const PAYMENT_METHOD_CASH = 'cash'; // 现金
    public const PAYMENT_METHOD_BANK_TRANSFER = 'bank_transfer'; // 银行转账
    public const PAYMENT_METHOD_DAOWAY = 'daoway'; // 到位平台支付

    public const PAYMENT_METHODS = [
        [
            'key' => self::PAYMENT_METHOD_WECHAT,
            'name' => '微信支付',
        ],
        [
            'key' => self::PAYMENT_METHOD_ALIPAY,
            'name' => '支付宝',
        ],
        [
            'key' => self::PAYMENT_METHOD_BANK_TRANSFER,
            'name' => '银行转账',
        ],
        [
            'key' => self::PAYMENT_METHOD_CASH,
            'name' => '现金',
        ],
    ];

    public const REFUND_STATUS_PENDING = 'pending';
    public const REFUND_STATUS_APPLIED = 'applied';
    public const REFUND_STATUS_PROCESSING = 'processing';
    public const REFUND_STATUS_SUCCESS = 'success';
    public const REFUND_STATUS_FAILED = 'failed';
    public static $refundStatusMap = [
        self::REFUND_STATUS_PENDING => '未退款',
        self::REFUND_STATUS_APPLIED => '已申请退款',
        self::REFUND_STATUS_PROCESSING => '退款中',
        self::REFUND_STATUS_SUCCESS => '退款成功',
        self::REFUND_STATUS_FAILED => '退款失败',
    ];

    public const SHIP_STATUS_DISTRIBUTION = 'distribution';
    public const SHIP_STATUS_PENDING = 'pending';
    public const SHIP_STATUS_DELIVERED = 'delivered';
    public const SHIP_STATUS_SUCCESS = 'success';
    public const SHIP_STATUS_RECEIVED = 'received';
    public static $shipStatusMap = [
        self::SHIP_STATUS_DISTRIBUTION => '待分配',
        self::SHIP_STATUS_PENDING => '待上门', //未上门(已分配待上门)
        self::SHIP_STATUS_DELIVERED => '已上门',
        self::SHIP_STATUS_SUCCESS => '已完成', //已完成(待评价) 只有订单详情页用到了
        self::SHIP_STATUS_RECEIVED => '客户已确认', //userorder received 用到
    ];
    //protected $dateFormat = 'U';
    protected $fillable = [
        'no',
        'total_amount',
        'city_id',
        'company_id',
        'full_address',
        'contact_name',
        'contact_phone',
        'remark',
        'paid_at',
        'payment_method',
        'payment_no',
        'refund_status',
        'refund_no',
        'closed',
        'reviewed',
        'ship_status',
        'ship_data',
        'assignDate',
        'assignTime',
        'is_main',
        'user_id',
        'pid',
        'bnames',
        'bids',
        'tran',
        'transaction_record_id',
        'coupon_code_id',
    ];

    protected $casts = [
        'closed' => 'boolean',
        'reviewed' => 'boolean',
        'ship_data' => 'json',
    ];

    protected $dates = [
        'paid_at',
    ];

    protected static function boot()
    {
        parent::boot();
        // 监听模型创建事件，在写入数据库之前触发
        static::creating(function ($model) {
            // 如果模型的 no 字段为空
            if (!$model->no) {
                // 调用 findAvailableNo 生成订单流水号
                $model->no = static::findAvailableNo();
                // 如果生成失败，则终止创建订单
                if (!$model->no) {
                    return false;
                }
            }
        });
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function channel()
    {
        return $this->belongsTo(OrderChannel::class, 'order_channelid');
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function items()
    {
        return $this->hasOne(OrderItem::class, 'order_id', 'id');
    }

    public function product()
    {
        return $this->belongsTo(Product::class);
    }

    public function productSKu()
    {
        return $this->belongsTo(ProductSku::class, 'product_sku_id');
    }

    public function productsUnit()
    {
        return $this->belongsTo(ProductsUnit::class, 'product_unit_id');
    }

    public function couponCode()
    {
        return $this->belongsTo(CouponCode::class);
    }

    public static function findAvailableNo()
    {
        /*
        // 订单流水号前缀
        $prefix = date('YmdHis');
        for ($i = 0; $i < 10; $i++) {
            // 随机生成 6 位的数字
            $no = $prefix . str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
            // 判断是否已经存在
            if (!static::query()->where('no', $no)->exists()) {
                return $no;
            }
        }
        \Log::warning('find order no failed');

        return false;
        */
        return TradeNoGeneratorUtil::get();
    }

    public static function getAvailableRefundNo()
    {
        do {
            // Uuid类可以用来生成大概率不重复的字符串
            $no = Uuid::uuid4()->getHex();
            // 为了避免重复我们在生成之后在数据库中查询看看是否已经存在相同的退款订单号
        } while (self::query()->where('refund_no', $no)->exists());

        return $no;
    }

    //获取最后支付时间在某一时间段内的用户的id
    public static function getPeriodLastPaidUserIds(string $startDate = '', string $endDate = '', string $orderBy = '')
    {
        $where = [
            ['paid_at', '>=', '0'],
        ];
        $having = [
            ['last_paid_date', '>=', $startDate],
            ['last_paid_date', '<=', $endDate],
        ];
        $query = self::where($where)->
        selectRaw('user_id, MAX(`paid_at`) AS last_paid_date, COUNT(DISTINCT orders.id) AS paid_count, SUM(order_items.price) AS paid_amount')->
        leftJoin('order_items', function ($join) {
            $join->on('orders.id', '=', 'order_items.order_id')->
            whereRaw('paid_at > "0"');
        })->
        groupBy('user_id')->
        having('last_paid_date', '>=', $startDate)->
        having('last_paid_date', '<=', $endDate);
        if ($orderBy) {
            list($orderByCol, $orderByDirect) = explode(' ', $orderBy);
            $query->orderBy($orderByCol, $orderByDirect);
        }
        $data = $query->get();
        return $data;
    }

    //获取某一用户总的购买数量和支付金额
    public static function getUserConsumeData(int $userId)
    {
        $where = [
            ['user_id', '=', $userId],
            ['paid_at', '<>', ''],
        ];
        $colsRaw = 'COUNT(orders.`id`) AS count, SUM(order_items.price) AS amount';
        $query = self::leftJoin('order_items', 'orders.id', '=', 'order_items.order_id')->
            where($where)->
            selectRaw($colsRaw);
        $data = $query->first();
        return $data;
    }

    /**
     * @param string $name
     * @return string
     */
    public static function getPaymentMethodKeyByName(string $name)
    {
        $keys = array_column(self::PAYMENT_METHODS, 'key');
        $names = array_column(self::PAYMENT_METHODS, 'name');

        return array_combine($names, $keys)[$name] ?? '';
    }

    /**
     * @param string $key
     * @return mixed|string
     */
    public static function getPaymentMethodNameByKey(string $key)
    {
        if ($key == Order::PAYMENT_METHOD_LJSH) {
            return '连接生活';
        }

        $keys = array_column(self::PAYMENT_METHODS, 'key');
        $names = array_column(self::PAYMENT_METHODS, 'name');

        return array_combine($keys, $names)[$key] ?? '';
    }
}
